package com.machine.bootstatemachine.machine;

import com.alibaba.fastjson.JSON;
import com.machine.bootstatemachine.enums.OrderEventEnum;
import com.machine.bootstatemachine.enums.OrderStatueEnum;
import com.machine.bootstatemachine.service.ordermachine.OrderStatusAction;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.statemachine.config.EnableStateMachineFactory;
import org.springframework.statemachine.config.EnumStateMachineConfigurerAdapter;
import org.springframework.statemachine.config.builders.*;
import org.springframework.statemachine.listener.StateMachineListener;
import org.springframework.statemachine.listener.StateMachineListenerAdapter;
import org.springframework.statemachine.state.State;

import java.util.EnumSet;

/**
 * @Author dai
 * @Date 2021/12/26
 */
@Slf4j
@Configuration
@EnableStateMachineFactory
public class OrderStateMachineConfig extends EnumStateMachineConfigurerAdapter<OrderStatueEnum, OrderEventEnum> {

    @Autowired
    private OrderStatusAction orderStatusAction;


    @Override
    public void configure(StateMachineConfigurationConfigurer<OrderStatueEnum, OrderEventEnum> config) throws Exception {
        config.withConfiguration()
                .autoStartup(true)
                .machineId("orderMachine")
                .listener(logListener());
    }

    private StateMachineListener<OrderStatueEnum, OrderEventEnum> logListener() {

        return new StateMachineListenerAdapter<OrderStatueEnum, OrderEventEnum>() {
            @Override
            public void stateChanged(State<OrderStatueEnum, OrderEventEnum> from, State<OrderStatueEnum, OrderEventEnum> to) {
                log.info("loggingListener() State  from {} changed to {}",
                        JSON.toJSONString(from), JSON.toJSONString(to));
            }

            @Override
            public void stateEntered(State<OrderStatueEnum, OrderEventEnum> state) {
                log.info("loggingListener() State {}", JSON.toJSONString(state));
            }

            @Override
            public void stateExited(State<OrderStatueEnum, OrderEventEnum> state) {
                log.info("loggingListener() State {}", JSON.toJSONString(state));
            }
        };
    }

    @Override
    public void configure(StateMachineStateConfigurer<OrderStatueEnum, OrderEventEnum> states) throws Exception {
        states.withStates()
                .initial(OrderStatueEnum.UN_PAY)
                .states(EnumSet.allOf(OrderStatueEnum.class));
    }

    @Override
    public void configure(StateMachineTransitionConfigurer<OrderStatueEnum, OrderEventEnum> transitions) throws Exception {
        transitions.withExternal()
                .source(OrderStatueEnum.UN_PAY).target(OrderStatueEnum.WAITING_FOR_RECEIVE)
                .event(OrderEventEnum.PAY)
                .action(orderStatusAction.payOrder(), orderStatusAction.payOrderError())
                .and()
                .withExternal()
                .source(OrderStatueEnum.WAITING_FOR_RECEIVE).target(OrderStatueEnum.DONE)
                .event(OrderEventEnum.RECEIVE)
                .action(orderStatusAction.orderDone(), orderStatusAction.orderDoneError());
    }

}
